﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using SharedLib.WinFormMVCFramework;
using TracyGUI.View;
using System.Windows.Forms;
using Tracy;
using Tracy.DataModel;
using TracyGUI.Controller.EntryTabs;
using Tracy.Handlers;
using TracyGUI.View.UIComponent;
using SharedLib;
using Tracy.Messages;
using SharedLib.MessageFramework;
using System.Diagnostics;
using SharedLib.Helpers;
using System.IO;
using TracyGUI.Model;
using SharedLib.MessageFramework.Messages;
using System.Threading;

namespace TracyGUI.Controller
{
    class MainViewController : ControllerBase<IMainView>, IController<IMainView>
    {
        ViewStateManager _viewStateManager;
        TracyConfigViewController _configViewController;
        EntryListViewController _entryListViewController;
        StatisticsViewController _statisticsViewController;
        DownloadCheckListViewController _downloadCheckListViewController;
        ImportExportViewController _dataImportViewController;
        NotifyIconViewController _notifyIconViewController;

        protected override IMainView ResolveView()
        {
            return Tracy.TracyFacade.Instance.DIContainer.Resolve<IMainView>();
        }

        private void LoadViewState(){
            _viewStateManager.LoadViewState(_configViewController);
            _viewStateManager.LoadViewState(_entryListViewController);
        }
        private void SaveViewState()
        {
            _viewStateManager.SaveViewState(_entryListViewController);
            _viewStateManager.SaveViewState(_configViewController);
            _viewStateManager.SaveToFile();
        }
        public MainViewController()
        {
            //View Events
            View.ViewClosing += new EventHandler<ViewClosingEventArgs>(MainView_ViewClosing);
            View.ShowAboutClicked += new EventHandler(View_ShowAboutClicked);
            View.ScanClicked += new EventHandler(View_ScanClicked);

            //Model Events
            FeedScanHandler.ResourcesFound += new EventHandler<SharedLib.GenericEventArgs<List<Resource>>>(FeedScanHandler_ResourcesFound);
            FileMonitorHandler.FilesUpdating += new EventHandler<GenericEventArgs<IList<MediaFile>>>(FileMonitorHandler_FilesUpdating);
            VersionCheckHandler.NewVersionFound += new EventHandler<GenericEventArgs<string>>(VersionCheckHandler_NewVersionFound);
            ImportExportManager.ResourceFound += new EventHandler<GenericEventArgs<Resource>>(ImportExportManager_ResourceFound);
            

            //Data Removal Management
            TracyFacade.Instance.EntryProvider.ItemsRemoved += new EventHandler<GenericEventArgs<IList<Entry>>>(EntryProvider_ItemsRemoved);
            TracyFacade.Instance.ResourceProvider.ItemsRemoved += new EventHandler<GenericEventArgs<IList<Resource>>>(ResourceProvider_ItemsRemoved);
            TracyFacade.Instance.MediaFileProvider.ItemsRemoved += new EventHandler<GenericEventArgs<IList<MediaFile>>>(MediaFileProvider_ItemsRemoved);

            //File Copy Management
            TracyFacade.Instance.EntryProvider.ItemsChanged += new EventHandler<GenericEventArgs<IList<DataChangeSet<Entry>>>>(EntryProvider_ItemsChanged);

            Init();
        }

        private void Init()
        {
            //Init
            Tracy.TracyFacade.Instance.ExceptionManager.Process(() =>
            {
                _configViewController = new TracyConfigViewController();
                _entryListViewController = new EntryListViewController();
                _statisticsViewController = new StatisticsViewController();
                _downloadCheckListViewController = new DownloadCheckListViewController();
                _dataImportViewController = new ImportExportViewController();
                _notifyIconViewController = new NotifyIconViewController();
                
                _viewStateManager = new ViewStateManager();
                View.ApplyLanguage(TracyFacade.Instance.LanguageManager);
                LoadViewState();

                if (TracyFacade.Instance.UserPreferencesManager.CurrentUserPreferences.FirstUseFlag)
                {
                    PreferencesViewController pvc = new PreferencesViewController();
                    pvc.View.ShowModal();
                }

                //Start Task Scheduler
                TracyFacade.Instance.TaskScheduler.StartTimer();
            }, "UI Policy");
        }

        //Move files
        void EntryProvider_ItemsChanged(object sender, GenericEventArgs<IList<DataChangeSet<Entry>>> e)
        {
            foreach (DataChangeSet<Entry> change in e.Data)
            {
                if (change.Data.SavePath != change.OriginalData.SavePath && !String.IsNullOrEmpty(change.OriginalData.SavePath))
                {
                    //SavePath Changed
                    if (MessageBox.Show(TracyFacade.Instance.LanguageManager.GetText("MessageBox_EntrySavePathChanged_Message"), TracyFacade.Instance.LanguageManager.GetText("MessageBox_EntrySavePathChanged_Title"), MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                    {
                        MoveMediaFiles(change.Data, change.OriginalData.SavePath);
                    }
                }
            }
        }

        private void MoveMediaFiles(Entry entry, string previousPath)
        {

            if (entry != null && !String.IsNullOrEmpty(previousPath))
            {

                List<MediaFile> filesToMove = Tracy.TracyFacade.Instance.MediaFileProvider.GetItemsByEntry(entry);

                for (int i = 0; i < filesToMove.Count; i++)
                {
                    MediaFile file = filesToMove[i];
                    if (file.Status == "Watched" || file.Status == "Ready")
                    {
                        file.Properties[MediaFile.KEY_PREVIOUS_STATUS] = file.Status;
                        file.Status = "Moving";
                        file.Properties[MediaFile.KEY_PREVIOUS_PATH] = previousPath;
                        Tracy.TracyFacade.Instance.MediaFileProvider.UpdateItem(file);
                    }
                }
                TaskMessage moveFileMessage = new TaskMessage(this, typeof(FileMonitorHandler), filesToMove);
                moveFileMessage.CallBack = new MessageCallback(msg =>
                {
                    Console.WriteLine("[" + DateTime.Now.ToString("HH:mm:ss fff") + "] Delete Folder: " + previousPath); 
                    //Delete folder
                    IOHelper.DeleteFolderIfEmpty(previousPath);
                });
                Tracy.TracyFacade.Instance.MessageDispatcher.EnqueueMessage(moveFileMessage);
            }
            //TODO:handle exception
        }

        //Remove related files
        void ResourceProvider_ItemsRemoved(object sender, GenericEventArgs<IList<Resource>> e)
        {
            List<MediaFile> fileList = new List<MediaFile>();
            foreach (Resource res in e.Data)
            {
                fileList.AddRange(Tracy.TracyFacade.Instance.MediaFileProvider.GetItemsByResource(res));
            }
            Tracy.TracyFacade.Instance.MediaFileProvider.RemoveItems(fileList);
        }

        //Remove related resources
        void EntryProvider_ItemsRemoved(object sender, GenericEventArgs<IList<Entry>> e)
        {
            List<Resource> resList = new List<Resource>();
            foreach (Entry entry in e.Data)
            {
                resList.AddRange(Tracy.TracyFacade.Instance.ResourceProvider.GetItemsByEntry(entry));
            }

            Tracy.TracyFacade.Instance.ResourceProvider.RemoveItems(resList);
        }

        //Delete Physical files
        void MediaFileProvider_ItemsRemoved(object sender, GenericEventArgs<IList<MediaFile>> e)
        {
            List<string> physicalFilesToDelete = new List<string>();
            StringWriter sw = new StringWriter();
            sw.Write(TracyFacade.Instance.LanguageManager.GetText("MessageBox_MediaFileDelete_Message"));
            //TODO: clear temp file as well
            foreach (MediaFile file in e.Data)
            {
                if (file.Status == "Ready" || file.Status == "Watched")
                {
                    physicalFilesToDelete.Add(file.GetSavedFilePath());
                    sw.Write("\r\n" + file.FileName);
                }
            }

            if (physicalFilesToDelete.Count > 0)
            {
                if (MessageBox.Show(sw.ToString(), TracyFacade.Instance.LanguageManager.GetText("MessageBox_MediaFileDelete_Title"), MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                {
                    List<string> folders = new List<string>();
                    foreach (string filePath in physicalFilesToDelete)
                    {
                        if (filePath != null)
                        {
                            string path = Path.GetDirectoryName(filePath);
                            if (path != null && !folders.Contains(path))
                            {
                                folders.Add(path);
                            }
                            if (File.Exists(filePath))
                            {
                                File.SetAttributes(filePath, FileAttributes.Normal);
                                File.Delete(filePath);
                            }
                        }
                    }

                    //Remove empty folders
                    foreach (string folder in folders)
                    {
                        IOHelper.DeleteFolderIfEmpty(folder);
                    }
                }
            }
        }

        #region View Events
        void View_ScanClicked(object sender, EventArgs e)
        {
            Tracy.TracyFacade.Instance.ExceptionManager.Process(() =>
            {
                //TODO: Scan a single entry
                TracyFacade.Instance.MessageDispatcher.EnqueueMessage(new TaskMessage(this, typeof(FeedScanHandler), null));
                TracyFacade.Instance.MessageDispatcher.EnqueueMessage(new TaskMessage(this, typeof(FileMonitorHandler), null));
            }, "UI Policy");
        }

        void View_ShowAboutClicked(object sender, EventArgs e)
        {
            Tracy.TracyFacade.Instance.ExceptionManager.Process(() =>
            {
                View.ShowAbout();
            }, "UI Policy");
        }

        void MainView_ViewClosing(object sender, ViewClosingEventArgs e)
        {
            Tracy.TracyFacade.Instance.ExceptionManager.Process(() =>
            {
                SaveViewState();
            }, "UI Policy");
            TracyFacade.Instance.Dispose();
            Application.ExitThread();
        }
        #endregion

        #region Model Events
        void FileMonitorHandler_FilesUpdating(object sender, GenericEventArgs<IList<MediaFile>> e)
        {
            List<DataChangeSet<MediaFile>> changes = new List<DataChangeSet<MediaFile>>();
            foreach (MediaFile newFile in e.Data)
            {
                MediaFile oldFile = TracyFacade.Instance.MediaFileProvider.GetItemByID(newFile.ID);
                changes.Add(new DataChangeSet<MediaFile>(oldFile, newFile));
                if (oldFile.Status != "Ready" && newFile.Status == "Ready") NotificationManager.Notify(this, TracyFacade.Instance.LanguageManager.GetText("Notification_MediaFileReady_Title"), newFile.FileName);
            }
            TracyFacade.Instance.MediaFileProvider.UpdateItems(changes);
        }

        void VersionCheckHandler_NewVersionFound(object sender, GenericEventArgs<string> e)
        {
            NotificationManager.Notify(this, TracyFacade.Instance.LanguageManager.GetText("Notification_NewVersionFound_Title"), e.Data + TracyFacade.Instance.LanguageManager.GetText("Notification_NewVersionFound_Message"), ToolTipIcon.Info, () =>
            {
                Process.Start("http://tracy.codeplex.com");
            });
        }

        void FeedScanHandler_ResourcesFound(object sender, SharedLib.GenericEventArgs<List<Resource>> e)
        {
            List<Resource> resourceList = e.Data as List<Resource>;

            for (int i = resourceList.Count - 1; i >= 0; i--) //sort desc
            {
                //Save resource
                Resource res = resourceList[i];
                res.Created = System.DateTime.Today.ToString();
                Tracy.TracyFacade.Instance.ResourceProvider.AddItem(res);

                _downloadCheckListViewController.ProcessResource(res, TracyFacade.Instance.DownloadManager.IsAutoDownloadMode);

            }
        }
        void ImportExportManager_ResourceFound(object sender, GenericEventArgs<Resource> e)
        {
            TracyFacade.Instance.ResourceProvider.AddItem(e.Data);
            _downloadCheckListViewController.ProcessResource(e.Data, false);
        }
        #endregion



    }
}
